{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "24103c51",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/examples/agent/mistral_agent.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99cea58c-48bc-4af6-8358-df9695659983",
   "metadata": {},
   "source": [
    "# Function Calling Anthropic Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "673df1fe-eb6c-46ea-9a73-a96e7ae7942e",
   "metadata": {},
   "source": [
    "This notebook shows you how to use our Anthropic agent, powered by function calling capabilities.\n",
    "\n",
    "**NOTE:** Only claude-3* models support function calling using Anthropic's API."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54b7bc2e-606f-411a-9490-fcfab9236dfc",
   "metadata": {},
   "source": [
    "## Initial Setup "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23e80e5b-aaee-4f23-b338-7ae62b08141f",
   "metadata": {},
   "source": [
    "Let's start by importing some simple building blocks.  \n",
    "\n",
    "The main thing we need is:\n",
    "1. the Anthropic API (using our own `llama_index` LLM class)\n",
    "2. a place to keep conversation history \n",
    "3. a definition for tools that our agent can use."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41101795",
   "metadata": {},
   "source": [
    "If you're opening this Notebook on colab, you will probably need to install LlamaIndex 🦙.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4985c578",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install llama-index\n",
    "%pip install llama-index-llms-anthropic\n",
    "%pip install llama-index-embeddings-openai"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fe08eb1-e638-4c00-9103-5c305bfacccf",
   "metadata": {},
   "source": [
    "Let's define some very simple calculator tools for our agent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3dd3c4a6-f3e0-46f9-ad3b-7ba57d1bc992",
   "metadata": {},
   "outputs": [],
   "source": [
    "def multiply(a: int, b: int) -> int:\n",
    "    \"\"\"Multiple two integers and returns the result integer\"\"\"\n",
    "    return a * b\n",
    "\n",
    "\n",
    "def add(a: int, b: int) -> int:\n",
    "    \"\"\"Add two integers and returns the result integer\"\"\"\n",
    "    return a + b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eeac7d4c-58fd-42a5-9da9-c258375c61a0",
   "metadata": {},
   "source": [
    "Make sure your ANTHROPIC_API_KEY is set. Otherwise explicitly specify the `api_key` parameter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4becf171-6632-42e5-bdec-918a00934696",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms.anthropic import Anthropic\n",
    "\n",
    "llm = Anthropic(model=\"claude-3-opus-20240229\", api_key=\"sk-...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "707d30b8-6405-4187-a9ed-6146dcc42167",
   "metadata": {},
   "source": [
    "## Initialize Anthropic Agent"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "798ca3fd-6711-4c0c-a853-d868dd14b484",
   "metadata": {},
   "source": [
    "Here we initialize a simple Anthropic agent with calculator functions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38ab3938-1138-43ea-b085-f430b42f5377",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.agent.workflow import FunctionAgent\n",
    "\n",
    "agent = FunctionAgent(\n",
    "    tools=[multiply, add],\n",
    "    llm=llm,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5f4a204",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.agent.workflow import ToolCallResult\n",
    "\n",
    "\n",
    "async def run_agent_verbose(query: str):\n",
    "    handler = agent.run(query)\n",
    "    async for event in handler.stream_events():\n",
    "        if isinstance(event, ToolCallResult):\n",
    "            print(\n",
    "                f\"Called tool {event.tool_name} with args {event.tool_kwargs}\\nGot result: {event.tool_output}\"\n",
    "            )\n",
    "\n",
    "    return await handler"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "500cbee4",
   "metadata": {},
   "source": [
    "### Chat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9450401d-769f-46e8-8bab-0f27f7362f5d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Called tool add with args {'a': 121, 'b': 2}\n",
      "Got result: 123\n",
      "Called tool multiply with args {'a': 123, 'b': 5}\n",
      "Got result: 615\n",
      "Therefore, (121 + 2) * 5 = 615\n"
     ]
    }
   ],
   "source": [
    "response = await run_agent_verbose(\"What is (121 + 2) * 5?\")\n",
    "print(str(response))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "538bf32f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ToolCallResult(tool_name='add', tool_kwargs={'a': 121, 'b': 2}, tool_id='toolu_01MH6ME7ppxGPSJcCMEUAN5Q', tool_output=ToolOutput(content='123', tool_name='add', raw_input={'args': (), 'kwargs': {'a': 121, 'b': 2}}, raw_output=123, is_error=False), return_direct=False), ToolCallResult(tool_name='multiply', tool_kwargs={'a': 123, 'b': 5}, tool_id='toolu_01JE5TVERND5YC97E68gYoPw', tool_output=ToolOutput(content='615', tool_name='multiply', raw_input={'args': (), 'kwargs': {'a': 123, 'b': 5}}, raw_output=615, is_error=False), return_direct=False)]\n"
     ]
    }
   ],
   "source": [
    "# inspect sources\n",
    "print(response.tool_calls)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf759040",
   "metadata": {},
   "source": [
    "### Managing Context/Memory\n",
    "\n",
    "By default, `.run()` is stateless. If you want to maintain state, you can pass in a `context` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0c9e5313",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.workflow import Context\n",
    "\n",
    "ctx = Context(agent)\n",
    "\n",
    "response = await agent.run(\"My name is John Doe\", ctx=ctx)\n",
    "response = await agent.run(\"What is my name?\", ctx=ctx)\n",
    "\n",
    "print(str(response))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cabfdf01-8d63-43ff-b06e-a3059ede2ddf",
   "metadata": {},
   "source": [
    "## Anthropic Agent over RAG Pipeline\n",
    "\n",
    "Build a Anthropic agent over a simple 10K document. We use OpenAI embeddings and claude-3-haiku-20240307 to construct the RAG pipeline, and pass it to the Anthropic Opus agent as a tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "48120dd4-7f50-426f-bc7e-a903e090d32e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--2025-03-24 12:52:55--  https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/10k/uber_2021.pdf\n",
      "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.109.133, ...\n",
      "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.\n",
      "HTTP request sent, awaiting response... 200 OK\n",
      "Length: 1880483 (1.8M) [application/octet-stream]\n",
      "Saving to: ‘data/10k/uber_2021.pdf’\n",
      "\n",
      "data/10k/uber_2021. 100%[===================>]   1.79M  8.98MB/s    in 0.2s    \n",
      "\n",
      "2025-03-24 12:52:56 (8.98 MB/s) - ‘data/10k/uber_2021.pdf’ saved [1880483/1880483]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "!mkdir -p 'data/10k/'\n",
    "!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/10k/uber_2021.pdf' -O 'data/10k/uber_2021.pdf'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "48c0cf98-3f10-4599-8437-d88dc89cefad",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.tools import QueryEngineTool\n",
    "from llama_index.core import SimpleDirectoryReader, VectorStoreIndex\n",
    "from llama_index.embeddings.openai import OpenAIEmbedding\n",
    "from llama_index.llms.anthropic import Anthropic\n",
    "\n",
    "embed_model = OpenAIEmbedding(\n",
    "    model_name=\"text-embedding-3-large\", api_key=\"sk-proj-...\"\n",
    ")\n",
    "query_llm = Anthropic(model=\"claude-3-haiku-20240307\", api_key=\"sk-...\")\n",
    "\n",
    "# load data\n",
    "uber_docs = SimpleDirectoryReader(\n",
    "    input_files=[\"./data/10k/uber_2021.pdf\"]\n",
    ").load_data()\n",
    "\n",
    "# build index\n",
    "uber_index = VectorStoreIndex.from_documents(\n",
    "    uber_docs, embed_model=embed_model\n",
    ")\n",
    "uber_engine = uber_index.as_query_engine(similarity_top_k=3, llm=query_llm)\n",
    "query_engine_tool = QueryEngineTool.from_defaults(\n",
    "    query_engine=uber_engine,\n",
    "    name=\"uber_10k\",\n",
    "    description=(\n",
    "        \"Provides information about Uber financials for year 2021. \"\n",
    "        \"Use a detailed plain text question as input to the tool.\"\n",
    "    ),\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ebfdaf80-e5e1-4c60-b556-20558da3d5e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.agent.workflow import FunctionAgent\n",
    "\n",
    "agent = FunctionAgent(tools=[query_engine_tool], llm=llm, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58c53f2a-0a3f-4abe-b8b6-97a974ec7546",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In summary, based on Uber's 2021 10-K filing, some of the company's key risk factors included:\n",
      "\n",
      "- Significant expected increases in operating expenses \n",
      "- Challenges attracting and retaining drivers, consumers, merchants, shippers, and carriers\n",
      "- Risks to Uber's brand and reputation\n",
      "- Challenges from Uber's historical workplace culture \n",
      "- Difficulties optimizing organizational structure and managing growth\n",
      "- Risks related to criminal activity by platform users\n",
      "- Risks from new offerings and technologies like autonomous vehicles\n",
      "- Data security and privacy risks\n",
      "- Climate change exposure \n",
      "- Reliance on third-party platforms\n",
      "- Regulatory and legal risks\n",
      "- Intellectual property risks\n",
      "\n",
      "In terms of growth opportunities and tailwinds, Uber's strategy in 2021 focused on restructuring by divesting certain markets and business lines, and instead partnering with and taking minority ownership positions in local ridesharing and delivery companies in those markets. This suggests Uber saw opportunities to still participate in the growth of those markets through its investments, rather than operating independently.\n"
     ]
    }
   ],
   "source": [
    "response = await agent.run(\n",
    "    \"Tell me both the risk factors and tailwinds for Uber?\"\n",
    ")\n",
    "print(str(response))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
